# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: xguo

import datetime
import json
import logging
import os

from absl import (flags, app)

from coin.experimental.xguo.convert_symbol_to_product import convert_symbol_to_product
from coin.strategy.mm.subscription import get_subscription_key
from coin.strategy.mm.dumper_base import run_from_archive
from coin.base.book.util import (
    convert_book_to_dict,
    human_readable_timestamp_record,
)


def _is_same_book(book1, book2):
  if book1 is None or book2 is None:
    return False
  else:
    return book1['asks'] == book2['asks'] and book1['bids'] == book2['bids']


class DumpStrategy(object):
  def __init__(self, products):
    self._products = products
    self._prev_book = None

  @staticmethod
  def print_as_json(dict_data):
    print(json.dumps(dict_data, default=str))

  def on_book_reset(self, book_builder_name, book_builder):
    for product in self._products:
      if book_builder_name == get_subscription_key(product):
        book_builder.subscribe_book(product, self.on_book)
        book_builder.subscribe_trade(product, self.on_trade)

  def on_book(self, book):
    dict_book = convert_book_to_dict(book)
    notional_qty = 1.5
    dict_book['true_ask'] = book.get_ask_price_by_qty(notional_qty)
    dict_book['true_bid'] = book.get_bid_price_by_qty(notional_qty)
    if not _is_same_book(dict_book, self._prev_book):
      self._prev_book = dict_book
      self.print_as_json(dict_book)

  def on_trade(self, trade):
    dict_trade = {'type': 'trade'}
    # noinspection PyProtectedMember
    dict_trade.update(trade._asdict())
    dict_trade.update(human_readable_timestamp_record(trade.timestamp))
    self.print_as_json(dict_trade)


def launch(root_dir, product_str, trading_date, machine, hours):
  product = convert_symbol_to_product(product_str)
  products = [product]
  start_time = trading_date
  end_time = start_time + datetime.timedelta(hours=hours)
  strategy = DumpStrategy(products)
  run_from_archive(
      products,
      strategy.on_book_reset,
      start_time,
      end_time,
      root_dir=root_dir,
      machine=[machine],
  )

  return 0


def main(_):
  product_str = flags.FLAGS.product
  trading_date = flags.FLAGS.trading_date
  machine = flags.FLAGS.machine
  assert trading_date, '--trading_date must be specified.'
  assert machine, '--machine must be specified.'
  assert product_str, '--product must be specified.'
  logging.info('Running for %s %s ...', trading_date, machine)
  trading_date = datetime.datetime.strptime(trading_date, '%Y%m%d')
  root_dir = os.path.expanduser(flags.FLAGS.root_dir)
  launch(root_dir, product_str, trading_date, machine, flags.FLAGS.hours)


if __name__ == '__main__':
  flags.DEFINE_string('product', '', 'product')

  flags.DEFINE_string('trading_date', '20190421', 'Trading date in form of %Y%m%d.')

  flags.DEFINE_string('machine', 'feed-01.ap-northeast-1.aws', 'Instance machine name.')

  flags.DEFINE_integer('hours', 24, 'Time span in hours from 00:00:00 UTC.')

  flags.DEFINE_string('root_dir', '~/data/flow', 'root_dir')

  app.run(main)
